/****************************************************\
CQueue.c
功能：C语言实现的循环队列
日期：2009年3月5日
版本：V1.2
作者：郭盖华
\****************************************************/

//#include  "ucos_ii.h"
#include  "CQueue.h"

void InitialQ(Queue *queue, QUEUE_ELEMENT *buf, int bufcnt)
{
	q_int i;
	queue->h = 0;
	queue->t = 0;
	queue->maxsize = bufcnt;
	queue->pBuf = buf;
	for(i = 0 ; i < bufcnt ; i++)
		queue->pBuf[i] = 0;
	QUEUE_CREATELOCK(queue);
}

void ReleaseQ(Queue *queue)
{
	QUEUE_RELEASELOCK(queue);
}

void QClear(Queue *queue)
{
#ifndef __QUEUE_LOCK__
	OS_CPU_SR  cpu_sr = 0;
#else
    INT8U   os_err;
#endif
    
    QUEUE_LOCK(queue);
    
    queue->h = queue->t;
    
    QUEUE_ULOCK(queue);
}

q_int QPush(Queue *queue, QUEUE_ELEMENT buf)
{
	q_int nRealTail;
#ifndef __QUEUE_LOCK__
	OS_CPU_SR  cpu_sr = 0;
#else
    INT8U   os_err;
#endif
	QUEUE_LOCK(queue);

	//(queue->tail + 1) % queue->maxsize
	nRealTail = queue->t + 1;
	if(nRealTail >= queue->maxsize )
		nRealTail -= queue->maxsize;

	//is full ?
	if(nRealTail == queue->h )
	{
		QUEUE_ULOCK(queue);
		return 0;
	}
	//OK push data
	queue->pBuf[queue->t] = buf;
	//queue->tail = (queue->tail + 1) % queue->maxsize;
	queue->t = nRealTail;

	QUEUE_ULOCK(queue);

	return 1;
}

QUEUE_ELEMENT QPop(Queue *queue)
{
	QUEUE_ELEMENT pRet;

#ifndef __QUEUE_LOCK__
	OS_CPU_SR  cpu_sr = 0;
#else
    INT8U   os_err;
#endif
	QUEUE_LOCK(queue);

	// is empty?
	if(queue->t == queue->h)
	{
		QUEUE_ULOCK(queue);
		return 0;
	}
	// OK pop data
	pRet = queue->pBuf[queue->h];
	//queue->h = (queue->h + 1) % queue->maxsize;
	queue->h++;
	if(queue->h >= queue->maxsize)
		queue->h -= queue->maxsize;

	QUEUE_ULOCK(queue);
	return pRet;
}

q_int QPopBuf(Queue *queue, QUEUE_ELEMENT *buf, q_int n)
{
	q_int nRet, i, a, b;
#ifndef __QUEUE_LOCK__
	OS_CPU_SR  cpu_sr = 0;
#else
	INT8U   os_err;
#endif
	QUEUE_LOCK(queue);

	nRet = queue->t - queue->h + queue->maxsize;
	if(nRet >= queue->maxsize)
		nRet -= queue->maxsize;
	
	if(nRet < n)
		n = nRet;
	
	a = n + queue->h;

	i = queue->h;
	if(a < queue->maxsize)
	{
		b = 0;			
		queue->h = a;
	}
	else
	{
		b = a - queue->maxsize;
		a = queue->maxsize;		
		queue->h = b;
	}
	
	for(; i < a ; i++)
		*buf++ = queue->pBuf[i];
	
	for(i = 0 ; i < b ; i++)
		*buf++ = queue->pBuf[i];			
			
	QUEUE_ULOCK(queue);
	
	return n;		
}

q_int QPushBuf(Queue *queue, QUEUE_ELEMENT *buf, q_int n)
{
	q_int nRet, i, a, b;
#ifndef __QUEUE_LOCK__
	OS_CPU_SR  cpu_sr = 0;
#else
    INT8U   os_err;
#endif
	QUEUE_LOCK(queue);

	nRet = queue->t - queue->h + queue->maxsize;
	if(nRet >= queue->maxsize)
		nRet -= queue->maxsize;

	nRet = queue->maxsize - nRet - 1; //空闲数据个数

	if(nRet < n)
		n = nRet;

	a = n + queue->t;

	i = queue->t;
	if(a < queue->maxsize)
	{
		b = 0;																				 
		queue->t = a;
	}
	else
	{
		b = a - queue->maxsize;
		a = queue->maxsize;		
		queue->t = b;
	}

	for(; i < a ; i++)
		queue->pBuf[i] = *buf++;

	for(i = 0 ; i < b ; i++)
		queue->pBuf[i] = *buf++;

	QUEUE_ULOCK(queue);

	return n;			
}

q_int QEmpty(Queue *queue)
{
	q_int ret;
#ifndef __QUEUE_LOCK__
	OS_CPU_SR  cpu_sr = 0;
#else
    INT8U   os_err;
#endif

	QUEUE_LOCK(queue);
	if(queue->t == queue->h)
		ret = 0;
	else
		ret = 1;
	QUEUE_ULOCK(queue);	

	return ret;
}

q_int QFull(Queue *queue)
{
	q_int nRealTail , ret;
//	INT8U	os_err;
#ifndef __QUEUE_LOCK__
	OS_CPU_SR  cpu_sr = 0;
#endif

	QUEUE_LOCK(queue);
		
	nRealTail = queue->t + 1;
	if(nRealTail >= queue->maxsize )
		nRealTail -= queue->maxsize;

	//is full ?
	if(nRealTail == queue->h )
		ret =  0;	
	else
		ret = 1;

	QUEUE_ULOCK(queue);

	return ret;
}

q_int QSize(Queue *queue)
{
	q_int nRet;
#ifndef __QUEUE_LOCK__
	OS_CPU_SR  cpu_sr = 0;
#else
    INT8U   os_err;
#endif
	QUEUE_LOCK(queue);

	//nRet = (m_tail - m_h + m_maxsize) % m_maxsize ;
	nRet = queue->t - queue->h + queue->maxsize;
	if(nRet >= queue->maxsize)
		nRet -= queue->maxsize;

	QUEUE_ULOCK(queue);
	return nRet;
}

q_int QSizeEx(Queue *queue)
{
	q_int nRet;

	//nRet = (m_tail - m_h + m_maxsize) % m_maxsize ;
	nRet = queue->t - queue->h + queue->maxsize;
	if(nRet >= queue->maxsize)
		nRet -= queue->maxsize;

	return nRet;
}

q_int QEmptyEx(Queue *queue)
{
	q_int ret;

	if(queue->t == queue->h)
		ret = 0;
	else
		ret = 1;

	return ret;
}
